<template>
  <div style="display: flex; height: 100%">
    <el-container>
      <div style="width: 22%; border-right: 1px solid #ccc; padding: 5px">
        <el-button type="primary" @click="onAddRole" icon="CirclePlus"
          >新增角色</el-button
        >
        <el-divider direction="horizontal" style="width: 95%"></el-divider>
        <el-select
          v-model="searchForm.appCode"
          placeholder="应用"
          @change="onSearch"
        >
          <el-option
            v-for="item in rolesApp"
            :key="item.code"
            :label="item.description"
            :value="item.code"
          ></el-option>
        </el-select>
        <el-tree
          :data="roleTree"
          :props="defaultProps"
          default-expand-all
          node-key="id"
          @node-click="handleRoleNodeClick"
        >
          <template #default="{ node, data }">
            <span class="custom-tree-node">
              <span>{{ node.label }}</span>
              <span class="tree-node-operations">
                <el-icon class="operation-icon" @click.stop="onEditRole(data)"
                  ><Edit />
                </el-icon>
                <el-icon class="operation-icon" @click.stop="onDeleteRole(data)"
                  ><Delete
                /></el-icon>
              </span>
            </span>
          </template>
        </el-tree>
      </div>
      <div style="width: 23%; border-right: 1px solid #ccc; padding: 5px">
        <el-row
          ><el-text class="cus-tree-title">{{
            selectedRole.description ? selectedRole.description : "角色菜单"
          }}</el-text></el-row
        >
        <el-divider direction="horizontal" style="width: 95%"></el-divider>
        <el-tree
          :data="menuTree"
          node-key="id"
          show-checkbox
          @node-click="handleMenuNodeClick"
          :default-expand-all="true"
          :props="treeProps"
          :check-strictly="false"
          :default-checked-keys="defaultCheckedKeys"
          :selectable="false"
        />
      </div>
      <div style="width: 55%; padding: 5px">
        <el-checkbox v-model="includeThisMenu" style="margin-left: 10px" :disabled="!selectedMenu.id"
          >包含{{
            selectedMenu.description ? selectedMenu.description : ""
          }}菜单</el-checkbox
        >
        <el-button
          type="primary"
          style="margin-left: 55%; text-align: right; width: 80px"
          @click="onSubmitPermission"
          >保存</el-button
        >
        <el-divider direction="horizontal" style="width: 95%"></el-divider>

        <el-table
          :ref="multiSelPermissionsTab"
          :data="selectedMenuPermissions"
          style="width: 100%"
          row-key="id"
        >
          <el-table-column type="selection" />
          <el-table-column prop="id" label="ID" v-if="false"></el-table-column>
          <el-table-column
            prop="name"
            label="名称"
            width="150px"
          ></el-table-column>
          <el-table-column prop="path" label="路径"></el-table-column>
          <el-table-column
            prop="operation"
            label="方法"
            width="80px"
          ></el-table-column>
        </el-table>
      </div>
    </el-container>
  </div>
  <el-dialog
    v-model="dialogRoleVisible"
    :title="isEditRole ? '修改角色' : '新增角色'"
    width="30%"
    header-class="dialog-custom-header"

  >
  <el-divider direction="horizontal" style="width: 95%"></el-divider>
    <el-form :model="newRoleForm" label-width="70px">
      <el-form-item label="应用编码" v-if="false">
        <el-input v-model="newRoleForm.appCode"></el-input>
      </el-form-item>
      <el-form-item label="角色名称" v-if="!isEditRole">
        <el-input v-model="newRoleForm.name"></el-input>
      </el-form-item>
      <el-form-item label="角色描述">
        <el-input v-model="newRoleForm.description"></el-input>
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="dialogRoleVisible = false">取消</el-button>
        <el-button type="primary" @click="onSubmitRole">确定</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script setup>
import { ref, reactive, computed, watch, nextTick } from "vue";
import { ElMessage } from "element-plus";
import { get, post, put, del } from "@/utils/request";
// 定义两个空的权限列表，用来保存要删除的权限和要新增的权限
const includeThisMenu = ref(false);
const assigningPermissions = ref([]);
const unAssigningPermissions = ref([]);

const rolesApp = ref([]);
const defaultCheckedKeys = ref([]);
const dialogRoleVisible = ref(false);
// const dialogPermissionVisible = ref(false);
const isEditRole = ref(false); // 是否为修改角色模式
const newRoleForm = reactive({
  id: null,
  appCode: null,
  name: null,
  description: null,
});
const multiSelPermissionsTab = ref(null);
const searchForm = reactive({
  appCode: null,
});
const roleTree = ref([]);
const selectedRole = reactive({
  id: null,
  appCode: null,
  name: null,
  description: null,
});
const selectedRolePermissions = ref([]);
const selectedRoleMenus = ref([]);

const menuTree = ref([]);
const selectedMenu = reactive({
  id: null,
  appCode: null,
  name: null,
  description: null,
  type: null,
  path: null,
  parent: null,
  sort: null,
  permissions: null,
  children: null,
});
const selectedMenuPermissions = ref([]);
const defaultProps = {
  children: "children",
  label: "description",
};

const treeProps = {
  children: "children",
  label: "description",
};

const handleMenuNodeClick = (data) => {
  Object.assign(selectedMenu, data);
  // selectedMenu = data;
  selectedMenuPermissions.value = data.permissions || [];
  if (
    selectedRoleMenus.value.some((m) => m.menuId === selectedMenu.id)
  ) {
    includeThisMenu.value = true;
  } else {
    includeThisMenu.value = false;
  }
  // 下次再渲染
  nextTick(() => {
    selectedMenuPermissions.value.forEach((row) => {
      selectedRolePermissions.value.find((permission) => {
        if (permission.id === row.id) {
          multiSelPermissionsTab.value.toggleRowSelection(row, true);
        }
      });
    });
  });
};

const onSearch = async (val) => {
  // 根据搜索条件，更新角色树
  let params = {
    appCode: val,
  };
  await get("/apm/roles", params)
    .then((res) => {
      // console.log("搜索结果:", res);
      if (res.data.code === 0) {
        roleTree.value = res.data.data.data;
        if (roleTree.value.length > 0) {
          if (!selectedRole.id) {
            Object.assign(selectedRole, roleTree.value[0]);
          }
          handleRoleNodeClick(selectedRole);
        }
        // selectedRolePermissions.value = [];
      } else if (res.data.code === 401) {
        sessionStorage.clear();
        window.location.assign("/login");
      } else {
        ElMessage.error(res.data.msg ? res.data.msg : res.data.message);
      }
    })
    .catch((e) => {
      ElMessage.error(e.message);
    });
};

const onAddRole = () => {
  if (!searchForm.appCode) {
    ElMessage.error("请先选择应用");
    return;
  }
  isEditRole.value = false;
  Object.keys(newRoleForm).forEach((key) => {
    newRoleForm[key] = null;
  });
  newRoleForm.appCode = searchForm.appCode;
  dialogRoleVisible.value = true;
};

const onEditRole = (data) => {
  isEditRole.value = true;
  Object.assign(newRoleForm, data);
  dialogRoleVisible.value = true;
};

const onDeleteRole = (data) => {
  del("/apm/roles/" + data.id)
    .then((res) => {
      // console.log("搜索结果:", res);
      if (res.data.code === 0) {
        onSearch(searchForm.appCode);
        ElMessage.success("删除成功");
      } else if (res.data.code === 401) {
        sessionStorage.clear();
        window.location.assign("/login");
      } else {
        ElMessage.error(res.data.msg ? res.data.msg : res.data.message);
      }
    })
    .catch((e) => {
      ElMessage.error(e.message);
    });
};

const onSubmitRole = async() => {
  let succ = false;
  if (isEditRole.value) {
    let payload = {
      description: newRoleForm.description,
    };
    await put("/apm/roles/" + newRoleForm.id, payload)
      .then((res) => {
        if (res.data.code === 0) {
          onSearch(searchForm.appCode);
          succ = true;
          ElMessage.success("修改成功");
        } else if (res.data.code === 401) {
          sessionStorage.clear();
          window.location.assign("/login");
        } else {
          ElMessage.error(res.data.msg ? res.data.msg : res.data.message);
        }
      })
      .catch((e) => {
        ElMessage.error(e.message);
      });
  } else {
    // 新增角色逻辑
    let payload = {
      appCode: newRoleForm.appCode,
      name: newRoleForm.name,
      description: newRoleForm.description,
    };
    await post("/apm/roles", payload)
      .then((res) => {
        if (res.data.code === 0) {
          onSearch(searchForm.appCode);
          succ = true;
          ElMessage.success("新增成功");
        } else if (res.data.code === 401) {
          sessionStorage.clear();
          window.location.assign("/login");
        } else {
          ElMessage.error(res.data.msg ? res.data.msg : res.data.message);
        }
      })
      .catch((e) => {
        ElMessage.error(e.message);
      });
  }
  if (succ) {
    dialogRoleVisible.value = false;
  }

};

const handleRoleNodeClick = async (data) => {
  // 清空菜单权限列表
  Object.keys(selectedMenu).forEach((key) => {
    selectedMenu[key] = null;
  });
  includeThisMenu.value = false;
  selectedMenuPermissions.value = [];
  Object.assign(selectedRole, data);
  // 读取角色权限
  await get("/apm/roles/" + selectedRole.id)
    .then((res) => {
      console.log("搜索结果:", res);
      if (res.data.code === 0) {
        selectedRolePermissions.value = res.data.data.permissions;
        selectedRoleMenus.value = res.data.data.menus;

        let dupCheckedKeys = selectedRolePermissions.value.map((p) => p.menuId);
        defaultCheckedKeys.value = [...new Set(dupCheckedKeys)];
      } else if (res.data.code === 401) {
        sessionStorage.clear();
        window.location.assign("/login");
      } else {
        ElMessage.error(res.data.msg ? res.data.msg : res.data.message);
      }
    })
    .catch((e) => {
      ElMessage.error(e.message);
    });

  let params = {
    appCode: searchForm.appCode,
  };
  // 读取菜单树
  await get("/apm/menus", params)
    .then((res) => {
      if (res.data.code === 0) {
        menuTree.value = res.data.data.data;
      } else if (res.data.code === 401) {
        sessionStorage.clear();
        window.location.assign("/login");
      } else {
        ElMessage.error(res.data.msg ? res.data.msg : res.data.message);
      }
    })
    .catch((e) => {
      ElMessage.error(e.message);
    });
};

const onSubmitPermission = async () => {
  // 获取当前选中权限
  if (!selectedRole.id) {
    ElMessage.error("请选择角色");
    return;
  }
  if (!selectedMenu.id) {
    ElMessage.error("请选择菜单");
    return;
  }
  assigningPermissions.value = [];
  unAssigningPermissions.value = [];
  // 获取当前菜单下所选中的权限
  let currentMenuCheckedPermissions =
    multiSelPermissionsTab.value.getSelectionRows();
  // 获取当前角色的当前菜单下所有的权限
  let currentMenuAssignedPermissions = selectedRolePermissions.value.filter(
    (permission) => permission.menuId === selectedMenu.id
  );
  // 填充新增权限列表,新的权限旧列表中找不到则新增
  currentMenuCheckedPermissions.forEach((permission) => {
    if (
      !currentMenuAssignedPermissions.some(
        (assignedPermission) => assignedPermission.id === permission.id
      )
    ) {
      assigningPermissions.value.push(permission.id);
    }
  });
  // 填充删除权限列表,旧列表中权限在新列表中找不到则删除
  currentMenuAssignedPermissions.forEach((permission) => {
    if (
      !currentMenuCheckedPermissions.some(
        (checkedPermission) => checkedPermission.id === permission.id
      )
    ) {
      unAssigningPermissions.value.push(permission.id);
    }
  });

  let payload = {
    menuId: selectedMenu.id,
    include: includeThisMenu.value,
    permissionsId: unAssigningPermissions.value,
  };

  let executeStatus = true;
  if (payload.permissionsId.length > 0) {
    // 开始删除权限
    await del("/apm/roles/" + selectedRole.id + "/permissions", payload)
      .then((res) => {
        // console.log("搜索结果:", res);
        if (res.data.code === 0) {
          console.log(res.data.message);
        } else if (res.data.code === 401) {
          sessionStorage.clear();
          window.location.assign("/login");
        } else {
          executeStatus = false;
          ElMessage.error(res.data.msg ? res.data.msg : res.data.message);
        }
      })
      .catch((e) => {
        executeStatus = false;
        ElMessage.error(e.message);
      });
  }
  // 继续增加权限
  payload.permissionsId = assigningPermissions.value;
  if (executeStatus) {
    await post("/apm/roles/" + selectedRole.id + "/permissions", payload)
      .then((res) => {
        // console.log("搜索结果:", res);
        if (res.data.code === 0) {
          console.log(res.data.message);
        } else if (res.data.code === 401) {
          sessionStorage.clear();
          window.location.assign("/login");
        } else {
          executeStatus = false;
          ElMessage.error(res.data.msg ? res.data.msg : res.data.message);
        }
      })
      .catch((e) => {
        executeStatus = false;
        ElMessage.error(e.message);
      });
  }
  if (executeStatus) {
    onSearch(searchForm.appCode);
    ElMessage.success("权限修改成功");
  }
};

onMounted(async () => {
  // 获取顶级角色列表
  await get("/apm/apps")
    .then((res) => {
      // console.log("搜索结果:", res);
      if (res.data.code === 0) {
        rolesApp.value = res.data.data.data;
        searchForm.appCode = rolesApp.value[0].code;
      } else if (res.data.code === 401) {
        sessionStorage.clear();
        window.location.assign("/login");
      } else {
        ElMessage.error(res.data.msg ? res.data.msg : res.data.message);
      }
    })
    .catch((e) => {
      ElMessage.error(e.message);
    });
  onSearch(searchForm.appCode);
});
</script>

